package com.czh.subject.infra.basic.service.impl;

import com.czh.subject.common.entity.PageResult;
import com.czh.subject.infra.basic.convert.SubjectInfoEsConverter;
import com.czh.subject.infra.basic.es.EsIndexInfo;
import com.czh.subject.infra.basic.es.EsRestClient;
import com.czh.subject.infra.basic.es.EsSearchRequest;
import com.czh.subject.infra.basic.es.EsSourceData;
import com.czh.subject.infra.basic.entity.EsSubjectFields;
import com.czh.subject.infra.basic.entity.SubjectInfoES;
import com.czh.subject.infra.basic.service.SubjectEsService;
import jakarta.annotation.Resource;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author caozaihui
 * @version 1.0
 * @since 2024/9/10 22:26
 */
@Service
public class SubjectEsServiceImpl implements SubjectEsService {


    @Resource
    private EsRestClient restClient;
    @Value("${es.cluster.active.subject.name}")
    private String subjectClusterName;
    @Value("${es.cluster.active.subject.index}")
    private String subjectIndexName;
    private EsIndexInfo getEsIndexInfo() {
        return new EsIndexInfo(subjectClusterName,subjectIndexName );
    }
    @Override
    public boolean insert(SubjectInfoES subjectInfoES) {
        EsSourceData subjectData = new EsSourceData();
        Map<String,Object> subjectMap = SubjectInfoEsConverter.convertToMap(subjectInfoES);
        subjectData.setDocId(subjectInfoES.getDocId().toString());
        subjectData.setData(subjectMap);
        return restClient.insertDoc(getEsIndexInfo(),subjectData);
    }

    @Override
    public PageResult<SubjectInfoES> querySubjectInfoES(SubjectInfoES reqsubjectInfoES) {
        PageResult<SubjectInfoES> subjectInfoESPageResult = new PageResult<>();
        EsSearchRequest esSearchRequest = getEsSearchRequest(reqsubjectInfoES);
        SearchResponse searchResponse = restClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);
        SearchHits searchHits = searchResponse.getHits();

        subjectInfoESPageResult.setPageNo(reqsubjectInfoES.getPageNo());
        subjectInfoESPageResult.setPageSize(reqsubjectInfoES.getPageSize());

        if (Objects.isNull(searchHits) || Objects.isNull(searchHits.getHits())){
            subjectInfoESPageResult.setTotal(0);
            return subjectInfoESPageResult;
        }
        List<SubjectInfoES> subjectInfoESList = new LinkedList<>();
        for (SearchHit hit : searchHits.getHits()) {
            SubjectInfoES subjectInfoES = SubjectInfoEsConverter.convertToSubjectInfoES(hit);
            subjectInfoESList.add(subjectInfoES);
        }
        subjectInfoESPageResult.setTotal(subjectInfoESList.size());
        subjectInfoESPageResult.setResult(subjectInfoESList);

        return subjectInfoESPageResult;
    }

    private static EsSearchRequest getEsSearchRequest(SubjectInfoES subjectInfoES) {
        EsSearchRequest esSearchRequest = new EsSearchRequest();
        BoolQueryBuilder builder =new BoolQueryBuilder();
//        MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder(EsSubjectFields.SUBJECT_NAME, subjectInfoES.getKeyWord());
//        builder.should(matchQueryBuilder);
        //boost增加权重
        //应查询题目
        MatchQueryBuilder subjectNameMatchQueryBuilder =
                QueryBuilders.matchQuery(EsSubjectFields.SUBJECT_NAME, subjectInfoES.getKeyWord()).boost(2);
        builder.should(subjectNameMatchQueryBuilder);
        //应查询答案
        MatchQueryBuilder subjectAnswerMatchQueryBuilder =
                QueryBuilders.matchQuery(EsSubjectFields.SUBJECT_ANSWER, subjectInfoES.getKeyWord());
        builder.should(subjectAnswerMatchQueryBuilder);
        //规定题目类型
        MatchQueryBuilder subjejctTypeMatchQueryBuilder;
        if (Objects.nonNull(subjectInfoES.getSubjectType())){
            subjejctTypeMatchQueryBuilder = QueryBuilders.matchQuery(EsSubjectFields.SUBJECT_TYPE, subjectInfoES.getSubjectType());
            builder.must(subjejctTypeMatchQueryBuilder);
        }
        //should至少匹配一个
        builder.minimumShouldMatch(1);
        //增加高亮 设置所有字段都进行高亮处理
        HighlightBuilder highlightBuilder = new HighlightBuilder().field("*").requireFieldMatch(false).encoder("html");
        highlightBuilder.preTags("<span style='color:red'>").postTags("</span>");

        esSearchRequest.setBoolQueryBuilder(builder);
        esSearchRequest.setFields(EsSubjectFields.FIELD_QUERY);
        esSearchRequest.setFrom((subjectInfoES.getPageNo()-1)*subjectInfoES.getPageSize());
        esSearchRequest.setSize(subjectInfoES.getPageSize());
        esSearchRequest.setHighlightBuilder(highlightBuilder);
        esSearchRequest.setNeedScroll(false);
        return esSearchRequest;
    }
}
